from ResistanceClass.StraightCircleSmoothWallPipe import StraightCircleSmoothWallPipe as CirclePipe
from ResistanceClass.StraightRectSmoothWallPipe import StraightRectSmoothWallPipe as RectPipe
from ResistanceClass.CurveCircleSmoothWallPipe import CurveCircleSmoothWallPipe as CurveCirclePipe
from ResistanceClass.CurveRectSmoothWallPipe import CurveRectSmoothWallPipe as CurveRectPipe
from ResistanceClass.CurveCircleSmoothSharpWallPipe import CurveCircleSmoothSharpWallPipe as ElbowSharp
import copy


class HandlerAddButton:
    range_limit_value = {
        'length': {'min_value': 0.005, 'max_value': float('inf')},
        'diameter': {'min_value': 0.002, 'max_value': 1.5},
        'angle': {'angle_pipe': {'min_value': 0.25, 'max_value': 180},
                  'angle_elbow': {'min_value': 20, 'max_value': 180}},
        'bend_radius': {'min_value': 0.5, 'max_value': float('inf')},
        'height': {'min_value': 0.002, 'max_value': 1.5},
        'width': {'min_value': 0.002, 'max_value': 1.5},
    }

    def __init__(self):
        self.angle_elbow = None

    def check_zero_in_values(self, input):
        check_number = input.split('.')
        if len(check_number) > 2:
            return True
        else:
            try:
                if str(int(check_number[0])) != check_number[0]:
                    return True
            except ValueError:
                return False
        return False

    def add_or_edit_elem(self, window, work_fluid):
        instance_elem = None
        type_element = window.choose_type_elem_cb.currentText()
        if type_element == 'Прямой участок':
            cross_section = window.straight_pipe.choose_type_cross_sec_cb.currentText()
            if cross_section == 'Круглое':
                instance_elem = CirclePipe(
                    fluid=work_fluid,
                    length=float(window.straight_pipe.circle_pipe.length.text().replace(',', '.')),
                    diameter=float(window.straight_pipe.circle_pipe.diameter.text().replace(',', '.')),
                )
            elif cross_section == 'Прямоугольное':
                instance_elem = RectPipe(
                    fluid=work_fluid,
                    length=float(window.straight_pipe.rect_pipe.length.text().replace(',', '.')),
                    width=float(window.straight_pipe.rect_pipe.width.text().replace(',', '.')),
                    height=float(window.straight_pipe.rect_pipe.height.text().replace(',', '.'))
                )
        elif type_element == 'Изогнутый участок':
            cross_section = window.curve_pipe.choose_type_cross_sec_cb.currentText()
            if cross_section == 'Круглое':
                instance_elem = CurveCirclePipe(
                    fluid=work_fluid,
                    diameter=float(window.curve_pipe.circle_pipe.diameter.text().replace(',', '.')),
                    bend_radius=float(window.curve_pipe.circle_pipe.bend_radius.text().replace(',', '.')),
                    bend_angle=float(window.curve_pipe.circle_pipe.angle.text().replace(',', '.')),
                )
            elif cross_section == 'Прямоугольное':
                instance_elem = CurveRectPipe(
                    fluid=work_fluid,
                    width=float(window.curve_pipe.rect_pipe.width.text().replace(',', '.')),
                    height=float(window.curve_pipe.rect_pipe.height.text().replace(',', '.')),
                    bend_radius=float(window.curve_pipe.rect_pipe.bend_radius.text().replace(',', '.')),
                    bend_angle=float(window.curve_pipe.rect_pipe.angle.text().replace(',', '.')),
                )
        elif type_element == 'Угольник':
            cross_section = window.elbow.choose_type_cross_sec_cb.currentText()
            if cross_section == 'Круглое':
                instance_elem = ElbowSharp(
                    fluid=work_fluid,
                    diameter=float(window.elbow.elbow_circle.diameter.text().replace(',', '.')),
                    bend_angle=float(window.elbow.elbow_circle.angle.text().replace(',', '.')),
                )

        return instance_elem

    def exception_element(self, window):
        params_current_widget = window.get_params_current_widget()
        string_errors = {}
        for param in params_current_widget:
            if param.objectName() == 'roughness':
                continue

            else:
                if param.objectName() == 'cross_section' or param.objectName() == 'type_element':
                    if params_current_widget[param] == '':
                        string_errors[param.objectName()] = 'Заполните поле'
                        continue
                else:
                    params_current_widget[param] = params_current_widget[param].replace(',', '.')
                    self.handler_number_value(string_errors, params_current_widget, param)
                    continue

        if len(string_errors) == 0:
            name_params_current_widget = window.get_name_params_element()
            for param_name in name_params_current_widget:
                if param_name == 'roughness':
                    continue
                else:
                    self.handler_range_value(string_errors, name_params_current_widget, param_name)
                    continue

        print(string_errors)
        return string_errors

    def handler_number_value(self, list_errors, params_dct, param):
        try:
            float(params_dct[param])
        except ValueError:
            list_errors[param.objectName()] = 'Введите число'

        else:
            if '.' not in params_dct[param] and params_dct[param][0] == '0':
                list_errors[param.objectName()] = 'Значение должно быть больше 0'

            elif params_dct[param][0] == '-':
                list_errors[param.objectName()] = 'Значение должно быть неотрицательным'

            elif all(char == '0' for char in params_dct[param].replace('.', '0')):
                list_errors[param.objectName()] = 'Некорректное значение'

            elif self.check_zero_in_values(params_dct[param]):
                list_errors[param.objectName()] = 'Значение должно быть больше 0'

    def handler_range_value(self, list_errors, name_params_dct, param_name):
        if param_name == 'angle':
            if name_params_dct.get('bend_radius'):
                if float(name_params_dct[param_name].replace(',', '.')) < \
                        self.range_limit_value[param_name]['angle_pipe']['min_value'] or \
                        float(name_params_dct[param_name].replace(',', '.')) > \
                        self.range_limit_value[param_name]['angle_pipe']['max_value']:
                    list_errors[
                        param_name] = f"Диапазон от {self.range_limit_value[param_name]['angle_pipe']['min_value']} " \
                                      f"до {self.range_limit_value[param_name]['angle_pipe']['max_value']} градусов"
            else:
                if float(name_params_dct[param_name].replace(',', '.')) < \
                        self.range_limit_value[param_name]['angle_elbow']['min_value'] or \
                        float(name_params_dct[param_name].replace(',', '.')) > \
                        self.range_limit_value[param_name]['angle_elbow']['max_value']:
                    list_errors[
                        param_name] = f"Диапазон от {self.range_limit_value[param_name]['angle_elbow']['min_value']} " \
                                      f"до {self.range_limit_value[param_name]['angle_elbow']['max_value']} градусов"

        else:

            if float(name_params_dct[param_name].replace(',', '.')) < self.range_limit_value[param_name]['min_value'] or \
                    float(name_params_dct[param_name].replace(',', '.')) > self.range_limit_value[param_name]['max_value']:
                if param_name != 'bend_radius':
                    list_errors[param_name] = f"Диапазон от {self.range_limit_value[param_name]['min_value']} " \
                                              f"до {self.range_limit_value[param_name]['max_value']} м"
                elif param_name == 'bend_radius':
                    list_errors[param_name] = f"Отношение радиуса гиба к диаметру < 0,5"

    def get_dict_params_widget(self, window):
        res = {}
        for k, v in window.get_params_current_widget().items():
            res[k.objectName()] = v
        return res

    def raise_exception(self, string_errors: list):
        if len(string_errors) > 0:
            raise ValueError
